﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace RainDrops
{
    class DropManager
    {
        public List<Drop> Drops = new List<Drop>();
        private Random rand = new Random();
        public Texture2D texture;
        public Rectangle bounds;
        private int count = 0;
        public float scaleMin = 0.2f, scaleMax = 1.0f;
        public float timeMin = 40f, timeMax =210f;
        public float dropAddTimerSet;
        public float dropAddTimer;
        private float currentGameTime;

        // Debug attributes
        private List<Drop> dropsOnScreen = new List<Drop>();
        public int debug_dropsStillOnScreen;
        public int debug_dropCount = 0;
        public bool debug_collision;
        public List<String> debug_collisionList = new List<String>();
        public String debug_collisionFlash = "none yet";
        public int debug_dropAddedCount = 0;

        public DropManager(int count, Texture2D texture, Rectangle bounds, float dropAddTime)
        {
            this.count = count;
            this.texture = texture;
            this.bounds = bounds;
            this.dropAddTimerSet = dropAddTime;
            for (int i = 0; i < count; i++)
            {
                AddDrop(i);
                debug_dropAddedCount++;
            }
        }

        public void AddDrop(int count)
        {
            Vector2 randomPos = RandomPosition();
            float randomScale = RandomScale();
            float randomTime = RandomTime();
            Drop newDrop = new Drop(randomPos, texture, new Rectangle(0, 0, texture.Width, texture.Height), Color.White, randomScale);

            foreach (Drop drop in Drops)
            {
                if (newDrop.IsCircleColliding(drop.Center, drop.CollisionRadius))
                {
                    newDrop.CurrentPosition = RandomPosition();
                }
            }

            newDrop.DropTime = randomTime;
            newDrop.DropID = count;

            Drops.Add(newDrop);
        }

        public void DropDown(Drop drop)
        {
            
            Vector2 destination = new Vector2(drop.CurrentPosition.X, bounds.Height + 20);
            Vector2 start = new Vector2(drop.CurrentPosition.X, drop.CurrentPosition.Y);
            drop.VelocityMotion(start, destination, new Vector2(0, 2), 4.0f);
            if ((drop.AnimationDone == true) || (!drop.onScreen(drop)))
            {
                Drops.Remove(drop);
            }

        }

        public void CombineDrops(Drop dropA, Drop dropB)
        {
            Vector2 centerOffset = (dropA.Center + dropB.Center) / 2;

            if ((dropB.Scale + dropA.Scale) > 1.0f) { dropB.Scale = 1.0f; }
            else { dropB.Scale = (dropA.Scale + dropB.Scale) / 1.3f; }
            dropB.SetNewCollisionRadius();
            Vector2 fullRadius = new Vector2(dropB.CollisionRadius, dropB.CollisionRadius);
            dropB.CurrentPosition = centerOffset - fullRadius;
            if (dropB.Scale > .7f)
            {
                dropB.Movement = false;
                dropB.DropTime = (float)MathHelper.Lerp(timeMin, timeMax, (float)rand.NextDouble());
            }

            // destroy dropA
            Drops.Remove(dropA);

            debug_collisionFlash = "collision: " + dropB.DropID.ToString() + " : " + dropA.DropID.ToString();
            // debug_collisionList.Add("collision:" + dropB.DropID.ToString());
            // System.Diagnostics.Debug.WriteLine("collision: " + dropB.DropID.ToString() +" : "+ dropA.DropID.ToString());
        }

        private float RandomScale()
        {
            float randomScale = (float)MathHelper.Lerp(scaleMin, scaleMax, (float)rand.NextDouble());
            if (randomScale >= 0.8f)
            {
                int randomOption = rand.Next(0,2);
                switch(randomOption)
                {
                    case 0:
                        randomScale = randomScale / 2;
                        break; 
                    case 1:
                        randomScale = randomScale / 3;
                        break;
                    case 2:
                        randomScale = randomScale - 0.1f;
                        break;
                }
            }
            return randomScale;
        }

        private Vector2 RandomPosition()
        {
            Vector2 randomPos= new Vector2(rand.Next(10, bounds.Width - 10), rand.Next(10, bounds.Height - 10));
            Vector2 positionCenter = randomPos + new Vector2(texture.Width / 2, texture.Height / 2);

            #region Old drop positioner 
            /*
            foreach (Drop drop in Drops)
            {
                if (drop.IsCircleColliding(positionCenter, (float)texture.Width))
                {
                    randomPos = new Vector2(rand.Next(10, bounds.Width - 10), rand.Next(10, bounds.Height - 10));
                }
            } 
             */
            #endregion

            #region New drop positioner
            /*
            for (int x = 0; x < Drops.Count; x++)
            {
                for (int y = x + 1; y < Drops.Count; y++)
                {
                    if (Drops[x].IsCircleColliding(Drops[y].Center, Drops[y].CollisionRadius))
                    {
                        // randomPos = new Vector2(randomPos.X + 10, randomPos.Y + 10);
                    }
                }
            } 
             */
            #endregion

            return randomPos;
        }

        public float RandomTime()
        {
            // Needs to be implemented so new times won't be less then older ones
            float randomTime = (float)MathHelper.Lerp(timeMin + this.currentGameTime, timeMax + this.currentGameTime, (float)rand.NextDouble());

            return randomTime;
        }

        public void Clear()
        {
            Drops.Clear();
        }

        public void Update(GameTime gameTime)
        {
            currentGameTime = (float)gameTime.TotalGameTime.TotalSeconds;
            double totalTime = gameTime.TotalGameTime.TotalSeconds;

            #region for loop for drops
            for (int i = 0; i < Drops.Count; i++)
            {
                Drops[i].Update(gameTime);
                if (Drops[i].Scale > .9f)
                {
                    DropDown(Drops[i]);
                }
                else if ((totalTime >= Drops[i].DropTime) && (Drops[i].Scale >= .6))
                {
                    DropDown(Drops[i]);
                }
            }
            #endregion

            for (int x = 0; x < Drops.Count; x++)
            {
                for (int y = x + 1; y < Drops.Count; y++)
                {
                    if ((Drops[x].IsCircleColliding(Drops[y].Center, Drops[y].CollisionRadius)) && (Drops[x].onScreen(Drops[x]) == true))
                    {
                        CombineDrops(Drops[x], Drops[y]);
                        debug_collision = true;
                    }
                    else { debug_collision = false; }
                }
            }

            dropAddTimer += (float)gameTime.ElapsedGameTime.TotalSeconds;
            if (dropAddTimer >= dropAddTimerSet)
            {
                AddDrop(1);
                dropAddTimer = 0;
            }
            // Debug code to pull drop count of drops on screen
            debug_dropsStillOnScreen = Drops.Count;
        }

        public void Draw(SpriteBatch spriteBatch)
        {
            foreach (Drop drop in Drops)
            {
                drop.Draw(spriteBatch);
            }
        }
    }
}
